package gatperdut.chato.core.interpreter.actions;

import gatperdut.chato.constants.CSConstantsCommandResult.CommandExecutionResult;
import gatperdut.chato.core.characters.BaseController;
import gatperdut.chato.core.interpreter.actions.generic.Action;
import gatperdut.chato.core.interpreter.grammar.comminfo.FillInfo;
import gatperdut.chato.core.item.DrinkController;
import gatperdut.chato.core.item.ItemController;
import gatperdut.chato.core.item.inventory.InventoryController;

public class FillAction extends Action {

    public FillAction( FillInfo info, BaseController entityController ) {
        super( info, entityController );
    }

    @Override
    public CommandExecutionResult perform() {
        checkForRunningCraft();

        DrinkController to;
        DrinkController from;

        if ( emptyEmote() ) {
            getEntityController().tx( "Empty emotes are not allowed." );
            return CommandExecutionResult.OK;
        }

        String emote = getLastPartEmote();
        if ( emote == null ) {
            getEntityController().tx( "Check your emote." );
            return CommandExecutionResult.OK;
        }

        if ( !checkUnindexedWord( getInfo().getToBeFilled() ) ) {
            return CommandExecutionResult.OK;
        }
        synchronized ( getEntityController().getInventoryController() ) {
            ItemController toBeFilled = getEntityController().getInventoryController().getHeldItemController( getInfo().getToBeFilled() );
            if ( toBeFilled == null ) {
                getEntityController().tx( "You don't seem to be holding that." );
                return CommandExecutionResult.OK;
            }
            synchronized ( toBeFilled ) {
                if ( !toBeFilled.isDrinkable() ) {
                    getEntityController().tx( toBeFilled.getShortDesc() + " cannot hold any liquid to be filled with." );
                    return CommandExecutionResult.OK;
                }

                to = (DrinkController) toBeFilled.getAmountController();

                if ( to.hasWholePortion() ) {
                    getEntityController().tx( toBeFilled.getShortDesc() + " is already full." );
                    return CommandExecutionResult.OK;
                }

                InventoryController inventoryControllerItemToFillFromIsIn = null;
                ItemController toFillFrom = null;
                if ( !getInfo().isGround() ) {
                    inventoryControllerItemToFillFromIsIn = getEntityController().getInventoryController();
                }
                if ( getInfo().isGround() || ( !getInfo().isGround() && inventoryControllerItemToFillFromIsIn == null ) ) {
                    inventoryControllerItemToFillFromIsIn = getEntityController().getRoomController().getInventoryController();
                }
                synchronized ( inventoryControllerItemToFillFromIsIn ) {
                    toFillFrom = findInRoomOrInventory( getInfo().getToFillFrom(), getInfo().isGround() );
                    if ( toFillFrom == null ) {
                        getEntityController().tx( "Where do you want to fill " + toBeFilled.getShortDesc() + " from?" );
                        return CommandExecutionResult.OK;
                    }
                    synchronized ( toFillFrom ) {
                        if ( !toFillFrom.isDrinkable() ) {
                            getEntityController().tx( toFillFrom.getShortDesc() + " cannot hold any liquid to fill from." );
                            return CommandExecutionResult.OK;
                        }

                        from = (DrinkController) toFillFrom.getAmountController();

                        if ( toBeFilled == toFillFrom ) {
                            getEntityController().tx( "You cannot fill " + toBeFilled.getShortDesc() + " from itself!" );
                            return CommandExecutionResult.OK;
                        }

                        if ( from.hasNoPortionLeft() ) {
                            getEntityController().tx( toFillFrom.getShortDesc() + " is empty." );
                        }
                        if ( !to.hasNoPortionLeft() && !to.containsThisFluid( from.getFluidContent() ) ) {
                            getEntityController().tx( "You cannot mix different liquids." );
                            return CommandExecutionResult.OK;
                        }

                        int amountToFill = Math.min( from.getPortion(), to.getPortionLeftToMax() );

                        from.consumePortion( amountToFill );
                        if ( from.isSetWithEmptyContainerOnTop() ) {
                            ItemController emptyContainer = toFillFrom.spawnFromSetOfNonEmptyContainers();
                            getEntityController().handleSpawnedItem( toFillFrom.getContainerController(), emptyContainer );
                        }
                        if ( to.isSetWithEmptyContainerOnTop() ) {
                            ItemController emptyContainer = toBeFilled.spawnFromSetOfEmptyContainers( from.getFluidContent(), amountToFill );
                            getEntityController().handleSpawnedItem( toBeFilled.getContainerController(), emptyContainer );
                        }
                        else {
                            to.addPortion( amountToFill );
                        }
                    }
                    getEntityController().getEchoes().txFill( toBeFilled, toFillFrom, emote );
                }
            }
        }
        return CommandExecutionResult.OK;
    }

    @Override
    public FillInfo getInfo() {
        return (FillInfo) super.getInfo();
    }

    @Override
    public boolean interruptsCrafting() {
        return false;
    }

}
